﻿#include <QString>
#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QTextStream>
#include <QMutex>
#include <QScopedPointer>
#include <QCoreApplication>
#include <QDebug>
#include <QDomElement>
#include <QThread>
#include "CLogMng.h"
#include "CLogWidget.h"

CLogMng& CLogMng::instance()
{
	static CLogMng instance;
	return instance;
}

void CLogMng::addMsg(const QString& sModuleName, const QString& sDeviceName, const QString& sFuncName, int nLevel, const QString& sLog)
{
	// 线程安全检查 - 如果不在对象所在线程，使用信号槽排队调用
	if (QThread::currentThread() != this->thread()) 
	{
		QMetaObject::invokeMethod(this, "processLogMsg", Qt::QueuedConnection,
			Q_ARG(QString, sModuleName),
			Q_ARG(QString, sDeviceName),
			Q_ARG(QString, sFuncName),
			Q_ARG(int, nLevel),
			Q_ARG(QString, sLog));
		return;
	}
	// 直接调用处理函数
	processLogMsg(sModuleName, sDeviceName, sFuncName, nLevel, sLog);
}

QWidget* CLogMng::createLogWidget(const QString& sModuleName, const QString& sDeviceName)
{
	QMutexLocker locker(&m_widgetMutex);
	int nType=0;
	if (sDeviceName != "")
	{
		nType = 0;
	}
	else
	{
		nType = 1;
	}
	QStringList sListDeviceName = sDeviceName.split(",");
	CLogWidget* pLogWidget = new CLogWidget(sModuleName, sListDeviceName.toVector(), nType);
	m_vecLogWidget.push_back(pLogWidget);
	return pLogWidget;
}

void CLogMng::destroyLogWidget(QWidget* widget)
{
	QMutexLocker locker(&m_widgetMutex);
	for (int i = 0; i < m_vecLogWidget.size(); i++)
	{
		if (widget == m_vecLogWidget[i])
		{
			m_vecLogWidget.removeAt(i);
			break; // 找到并删除后立即退出循环
		}
	}
}

SLogLevelConfig CLogMng::getLogLevelConfig(int nLevel)
{
	if (m_mapLogLevelConfigs.contains(nLevel))
	{
		return m_mapLogLevelConfigs[nLevel];
	}
	else
	{
		SLogLevelConfig sConfig;
		return sConfig;
	}
}

void CLogMng::saveConfig()
{
	QDomDocument doc;

	// 添加XML声明
	QDomProcessingInstruction instruction = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"");
	doc.appendChild(instruction);

	// 添加注释
	QDomComment comment = doc.createComment(QString::fromLocal8Bit("日志配置"));
	doc.appendChild(comment);

	// 创建根元素
	QDomElement root = doc.createElement("LogConfig");
	doc.appendChild(root);

	// Main配置部分
	QDomElement mainElem = doc.createElement("Main");
	root.appendChild(mainElem);

	// 添加Main配置项（带注释）
	auto createMainElementWithComment = [&](const QString& tagName, const QString& value, const QString& commentText)
	{
		// 添加注释
		QDomComment comment = doc.createComment(commentText);
		mainElem.appendChild(comment);

		// 添加配置元素
		QDomElement elem = doc.createElement(tagName);
		QDomText text = doc.createTextNode(value);
		elem.appendChild(text);
		mainElem.appendChild(elem);
	};

	createMainElementWithComment("IsShowLimit", m_isShowLimit ? "1" : "0", QString::fromLocal8Bit("IsShowLimit: 主页表格是否设置条数上限 0否1是"));
	createMainElementWithComment("ShowLimit", QString::number(m_showLimit), QString::fromLocal8Bit("ShowLimit: 主页表格显示条数上限"));
	createMainElementWithComment("ShowDescend", m_showDescend ? "1" : "0", QString::fromLocal8Bit("ShowDescend: 表格显示顺序 0 正序 1 倒序"));
	createMainElementWithComment("TableGridColor", m_tableGridColor.name(), QString::fromLocal8Bit("TableGridColor: 表格框线颜色"));
	createMainElementWithComment("TableBackColor", m_tableBackColor.name(), QString::fromLocal8Bit("TableBackColor: 表格空白部分背景色"));
	createMainElementWithComment("AutoClearType", QString::number(m_autoClearType), QString::fromLocal8Bit("AutoClearType: 自动清理类型 0关 1按日 2按月"));
	createMainElementWithComment("ClearFreq", QString::number(m_clearFreq, 'f', 1), QString::fromLocal8Bit("ClearFreq: 清理频率 单位小时"));
	createMainElementWithComment("ClearRange", QString::number(m_clearRange), QString::fromLocal8Bit("ClearRange: 清理时限 按日时为天数 按月时为月数"));

	// LogLevel配置部分
	QDomElement logLevelElem = doc.createElement("LogLevel");
	root.appendChild(logLevelElem);
	// 添加LogLevel配置注释
	QDomComment logLevelComment = doc.createComment(QString::fromLocal8Bit("日志等级配置 ID: 序号, Desc: 描述, TextColor: 文本颜色, BackColor: 背景颜色, IconPath: 图标路径"));
	logLevelElem.appendChild(logLevelComment);
	// 添加所有日志等级配置（使用QMap迭代）
	for (auto it = m_mapLogLevelConfigs.begin(); it != m_mapLogLevelConfigs.end(); ++it)
	{
		const SLogLevelConfig& config = it.value();
		QDomElement levelElem = doc.createElement("Level");

		levelElem.setAttribute("ID", QString::number(config.id));
		levelElem.setAttribute("Desc", config.desc);
		levelElem.setAttribute("TextColor", config.textColor.name());
		levelElem.setAttribute("BackColor", config.backColor.name());
		levelElem.setAttribute("IconPath", config.iconPath);
		logLevelElem.appendChild(levelElem);
	}

	// 保存到文件
	QString configFilePath = QCoreApplication::applicationDirPath() + "/Log/LogConfig.xml";
	QFile file(configFilePath);
	if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
	{
		return;
	}

	QTextStream stream(&file);
	stream.setCodec("UTF-8");
	doc.save(stream, 4); // 缩进为4个空格
	file.close();
	for (int i = 0; i < m_vecLogWidget.size(); i++)
	{
		if (m_vecLogWidget[i] != nullptr)
		{
			m_vecLogWidget[i]->onConfig();
		}
	}
}

QString CLogMng::getLevelString(int nLevel) const
{
	if (m_mapLogLevelConfigs.contains(nLevel))
	{
		return m_mapLogLevelConfigs[nLevel].desc;
	}
	else
	{
		return QString::fromLocal8Bit("未知");
	}
}

CLogMng::CLogMng()
{
	// 确保对象在主线程
	if (QThread::currentThread() != qApp->thread())
	{
		qWarning() << "CLogMng created in non-main thread, moving to main thread";
		this->moveToThread(qApp->thread());
	}
	init();
}

CLogMng::~CLogMng()
{
	QMutexLocker locker(&m_widgetMutex);
	m_vecLogWidget.clear();
}

void CLogMng::init()
{
	loadConfig();
}

void CLogMng::loadConfig()
{
	QString configFilePath = QCoreApplication::applicationDirPath() + "/Log/LogConfig.xml";
	QFile file(configFilePath);

	// 如果配置文件不存在，创建默认配置
	if (!file.exists())
	{
		createDefaultConfig();
		return;
	}

	if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
	{
		createDefaultConfig(); // 打开失败也创建默认配置
		return;
	}

	QDomDocument doc;
	QString errorMsg;
	int errorLine, errorColumn;
	if (!doc.setContent(&file, &errorMsg, &errorLine, &errorColumn))
	{
		qCritical() << "Failed to parse XML config file:" << errorMsg
			<< "at line" << errorLine << "column" << errorColumn;
		file.close();
		createDefaultConfig(); // 解析失败也创建默认配置
		return;
	}
	file.close();

	QDomElement root = doc.documentElement();
	if (root.isNull() || root.tagName() != "LogConfig")
	{
		qCritical() << "Invalid config file: root element is not LogConfig";
		createDefaultConfig(); // 格式错误也创建默认配置
		return;
	}

	// 解析Main配置
	QDomElement mainElement = root.firstChildElement("Main");
	if (!mainElement.isNull())
	{
		parseMainConfig(mainElement);
	}

	// 解析LogLevel配置
	QDomElement logLevelElement = root.firstChildElement("LogLevel");
	if (!logLevelElement.isNull())
	{
		parseLogLevelConfig(logLevelElement);
	}
	return;
}

void CLogMng::createDefaultConfig()
{
	QString configFilePath = QCoreApplication::applicationDirPath() + "/Log/LogConfig.xml";

	// 确保Log目录存在
	QDir logDir(QCoreApplication::applicationDirPath() + "/Log");
	if (!logDir.exists()) 
	{
		if (!logDir.mkpath("."))
		{
			qCritical() << "Failed to create Log directory:" << logDir.path();
			return;
		}
	}

	// 设置默认配置值
	m_isShowLimit = true;
	m_showLimit = 500;
	m_showDescend = true;
	m_tableGridColor = QColor("#000000");
	m_tableBackColor = QColor("#FFFFFF");
	m_autoClearType = 1;
	m_clearFreq = 24.0;
	m_clearRange = 180;

	// 默认的5个日志等级
	SLogLevelConfig level1;
	level1.id = 1;
	level1.desc = QString::fromLocal8Bit("系统信息");
	level1.textColor = QColor("#FFFFFF");
	level1.backColor = QColor("#444444");
	level1.iconPath = ":LogModule/qss/Running.png";
	m_mapLogLevelConfigs[1] = level1;

	SLogLevelConfig level2;
	level2.id = 2;
	level2.desc = QString::fromLocal8Bit("正常");
	level2.textColor = QColor("#32B372");
	level2.backColor = QColor("#444444");
	level2.iconPath = ":LogModule/qss/Debug.png";
	m_mapLogLevelConfigs[2] = level2;

	SLogLevelConfig level3;
	level3.id = 3;
	level3.desc = QString::fromLocal8Bit("工艺报警");
	level3.textColor = QColor("#FEBC2C");
	level3.backColor = QColor("#444444");
	level3.iconPath = ":LogModule/qss/Warning1.png";
	m_mapLogLevelConfigs[3] = level3;

	SLogLevelConfig level4;
	level4.id = 4;
	level4.desc = QString::fromLocal8Bit("系统异常报警");
	level4.textColor = QColor("#FE5F57");
	level4.backColor = QColor("#444444");
	level4.iconPath = ":LogModule/qss/Hardware.png";
	m_mapLogLevelConfigs[4] = level4;

	SLogLevelConfig level5;
	level5.id = 5;
	level5.desc = QString::fromLocal8Bit("设备故障");
	level5.textColor = QColor("#FF00FF");
	level5.backColor = QColor("#444444");
	level5.iconPath = ":LogModule/qss/Warning2.png";
	m_mapLogLevelConfigs[5] = level5;
	// 保存默认配置到文件
	saveConfig();
}

bool CLogMng::parseMainConfig(const QDomElement& element)
{
	// IsShowLimit
	QDomElement isShowLimitElem = element.firstChildElement("IsShowLimit");
	if (!isShowLimitElem.isNull())
	{
		m_isShowLimit = (isShowLimitElem.text().toInt() == 1);
	}

	// ShowLimit
	QDomElement showLimitElem = element.firstChildElement("ShowLimit");
	if (!showLimitElem.isNull()) 
	{
		m_showLimit = showLimitElem.text().toInt();
	}

	// ShowDescend
	QDomElement showDescendElem = element.firstChildElement("ShowDescend");
	if (!showDescendElem.isNull()) 
	{
		m_showDescend = (showDescendElem.text().toInt() == 1);
	}

	// TableGridColor
	QDomElement gridColorElem = element.firstChildElement("TableGridColor");
	if (!gridColorElem.isNull()) 
	{
		m_tableGridColor = QColor(gridColorElem.text());
	}

	// TableBackColor
	QDomElement backColorElem = element.firstChildElement("TableBackColor");
	if (!backColorElem.isNull()) 
	{
		m_tableBackColor = QColor(backColorElem.text());
	}

	// AutoClearType
	QDomElement autoClearTypeElem = element.firstChildElement("AutoClearType");
	if (!autoClearTypeElem.isNull()) 
	{
		m_autoClearType = autoClearTypeElem.text().toInt();
	}

	// ClearFreq
	QDomElement clearFreqElem = element.firstChildElement("ClearFreq");
	if (!clearFreqElem.isNull()) 
	{
		m_clearFreq = clearFreqElem.text().toDouble();
	}

	// ClearRange
	QDomElement clearRangeElem = element.firstChildElement("ClearRange");
	if (!clearRangeElem.isNull()) 
	{
		m_clearRange = clearRangeElem.text().toInt();
	}

	return true;
}

bool CLogMng::parseLogLevelConfig(const QDomElement& element)
{
	m_mapLogLevelConfigs.clear();
	QDomElement levelElem = element.firstChildElement("Level");
	while (!levelElem.isNull()) 
	{
		SLogLevelConfig config;
		// ID
		config.id = levelElem.attribute("ID").toInt();
		// Desc
		config.desc = levelElem.attribute("Desc");
		// TextColor
		config.textColor = QColor(levelElem.attribute("TextColor"));
		// BackColor
		config.backColor = QColor(levelElem.attribute("BackColor"));
		// IconPath
		config.iconPath = levelElem.attribute("IconPath");
		m_mapLogLevelConfigs.insert(config.id,config);
		levelElem = levelElem.nextSiblingElement("Level");
	}

	return true;
}

QString CLogMng::getLogFilePath(const QString& sModuleName, const QString& sDeviceName) const
{
	// 获取应用程序运行目录
	QString appDir = QCoreApplication::applicationDirPath();
	if (appDir.isEmpty())
	{
		qWarning() << "Failed to get application directory";
		return "";
	}

	// 构建完整路径：程序目录/Log/sModuleName/sDeviceName/年/月/
	QDateTime current = QDateTime::currentDateTime();
	QString year = current.toString("yyyy");
	QString Month = current.toString("yyyyMM");
	QString yearMonthDay = current.toString("yyyyMMdd");

	QString logDir = QString("%1/Log/%2/%3/%4/%5/")
		.arg(appDir)
		.arg(sModuleName)
		.arg(sDeviceName)
		.arg(year)
		.arg(Month);

	// 文件名：sDeviceName + 年月日.log
	QString fileName = QString("%1%2.log")
		.arg(sDeviceName)
		.arg(yearMonthDay);

	return QDir(logDir).absoluteFilePath(fileName);
}

void CLogMng::ensureDirExists(const QString& path) const
{
	QDir dir(path);
	if (!dir.exists())
	{
		if (!dir.mkpath("."))
		{
			qWarning() << "Failed to create directory:" << path;
		}
	}
}

void CLogMng::processLogMsg(const QString& sModuleName, const QString& sDeviceName, const QString& sFuncName, int nLevel, const QString& sLog)
{
	// 日志级别过滤
	if (nLevel < m_minLogLevel)
	{
		return;
	}

	QMutexLocker locker(&m_writeMutex);
	try
	{
		// 获取日志文件路径
		QString logFilePath = getLogFilePath(sModuleName, sDeviceName);
		if (logFilePath.isEmpty())
		{
			return;
		}

		// 确保目录存在
		ensureDirExists(QFileInfo(logFilePath).absolutePath());

		// 打开日志文件（追加模式）
		QFile logFile(logFilePath);
		if (!logFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text))
		{
			qWarning() << "Failed to open log file:" << logFilePath << "Error:" << logFile.errorString();
			return;
		}

		// 格式化日志内容
		QString levelStr = getLevelString(nLevel);
		QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
		QString formattedLog = QString("[%1],[%2],[%3],[%4]\n")
			.arg(levelStr)
			.arg(timestamp)
			.arg(sFuncName)
			.arg(sLog);

		// 写入日志
		QTextStream stream(&logFile);
		stream.setCodec("UTF-8");
		stream << formattedLog;
		stream.flush();

		logFile.close();
		// 创建日志数据对象
		QSharedPointer<LogData> logData = QSharedPointer<LogData>::create(
			nLevel, levelStr, timestamp, sModuleName, sDeviceName, sFuncName, sLog);
		QMutexLocker locker(&m_widgetMutex);
		// 通知所有有效的日志控件
		for (const QPointer<CLogWidget>& widget : m_vecLogWidget)
		{
			if (!widget.isNull())
			{
				widget->onLogAdded(logData);
			}
		}
	}
	catch (const std::exception& e)
	{
		qCritical() << "Logging failed with exception:" << e.what();
	}
}

